package ualrcdg.shared.dto;

import ualrcdg.shared.exceptions.CDGTypeException;

/**
 * Simple implementation of the "simpleProperty" object. See CDG XML Specifications: Game Descriptor Files.
 */
public class SimpleProperty< T >
{
	private final String id;
	private final String name;
	/*	LATER change className member to Class<T> type to avoid unchecked casts
	 * 	change getValue implementation to the following
	 * 	public T getValue()
	 * 	{
	 * 		return this.clazz.cast(this.value);
	 * 	}
	 */
	private final String className;
	private T value = null;
	
	/*
	 * Allow only known immutable types
	 */
	static private Class<?>[] validTypes =
	{
		java.lang.Boolean.class,
		
		java.lang.Character.class,
		
		java.lang.Byte.class,
		java.lang.Short.class,
		java.lang.Integer.class,
		java.lang.Long.class,
		java.math.BigInteger.class,
		
		java.lang.Float.class,
		java.lang.Double.class,
		java.math.BigDecimal.class,
		
		java.lang.String.class
	};
	
	/**
	 * Primary constructor
	 *
	 * @param id the id of the SimpleProperty object to be created
	 * @param name the name of the SimpleProperty object to be created
	 * @param value the value of the SimpleProperty object to be created
	 * @throws CDGTypeException If the initial value provided (and thus the implied value type) is not supported 
	 */
	public SimpleProperty( String id, String name, T value ) throws CDGTypeException
	{
		if( !isValidType( value.getClass( ) ) )
		{
			throw new CDGTypeException( "Cannot create property of type: " + value.getClass( ).getName( ) );
		}
		this.id = id;
		this.name = name;
		this.className = value.getClass( ).getName( );
		this.value = value;
		
		System.out.println( "Parsed: " + this.toString( ) );
	}

	/**
	 * Copy constructor
	 * 
	 * @param o the SimpleProperty that should be deep-copied into the newly created SimpleProperty object
	 */
	public SimpleProperty( SimpleProperty<T> o )
	{
		this.id = o.id;
		this.name = o.name;
		this.value = o.value;
		this.className = this.value.getClass( ).getName( );
		
		System.out.println( "Parsed: " + this.toString( ) );
	}
	
	/*
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString( )
	{
		return "SimpleProperty [id=" + id + ", name=" + name + ", className=" + className + ", value=" + value + "]";
	}

	/**
	 * Determines whether a particular class is a SimpleProperty-allowable type
	 * 
	 * @param T the class to check
	 * @return true if the class is an acceptable SimpleProperty type, false otherwise
	 */
	private boolean isValidType( Class<?> T )
	{
		for( Class<?> c : validTypes )
		{
			if( c.equals( T ) )
			{
				return true;
			}
		}
		return false;
	}
	
	/**
	 * @return the value of this SimpleProperty instance
	 */
	public T getValue( )
	{
		return (T)value;
	}

	/**
	 * @param value the value to set for this SimpleProperty instance
	 */
	public void setValue( T value )
	{
		this.value = value;
	}

	/**
	 * @return the id of this SimpleProperty instance
	 */
	public String getId( )
	{
		return id;
	}

	/**
	 * @return the name of this SimpleProperty instance
	 */
	public String getName( )
	{
		return name;
	}

	/**
	 * @return the className of this SimpleProperty instance
	 */
	public String getClassName( )
	{
		return className;
	}
}
